﻿/*
 * io.cpp
 *
 *  Created on: 2017年6月15日
 *      Author: work
 */

#include <dm/os/io/io.hpp>
#include <unistd.h>
#include <dm/os/log/logger.hpp>
#include <sys/socket.h>

namespace dm{
namespace os{
namespace io{

static const char* logModule = "CIo.io.os.dm";

CIo::CIo():m_fd(-1),m_address(),m_txBySend(false){
}

CIo::CIo( int fd ):m_fd(fd),m_address(),m_lastOpen(dm::CTimeStamp::cur()),m_txBySend(false){
	log().debug(THISMODULE "通过文件描述符%d构建",m_fd);
}

CIo::~CIo(){
	close();
}

bool CIo::open(){
	if( !isOpenable() ){
		log().warnning(THISMODULE "设备(%s)不支持打开操作",typeName());
		return false;
	}

	close();

	if( open_in(m_address) ){
		m_lastOpen = dm::CTimeStamp::cur();
		resetCounter();
		return true;
	}

	return false;
}

bool CIo::open( const com::CAddress& addr ){
	if( !setAddress(addr) ){
		log().warnning(THISMODULE "设备(%s)不支持该地址(%s)",typeName(),addr.toString().c_str());
		return false;
	}

	return open();
}

bool CIo::open( const char* addr ){
	if( !setAddress(addr) ){
		log().warnning(THISMODULE "设备(%s)不支持该地址(%s)",typeName(),addr);
		return false;
	}

	return open();
}

bool CIo::close(){
	if( m_fd>0 ){
		::close(m_fd);
		m_fd = -1;
		m_lastClose = dm::CTimeStamp::cur();
	}

	return true;
}

bool CIo::isOpen()const{
	return m_fd>=0;
}

bool CIo::isOpenable()const{
	switch( type() ){
	case com::CAddress::SerialPort:
	case com::CAddress::TcpClient:
	case com::CAddress::TcpBindClient:
	case com::CAddress::TcpServer:
	case com::CAddress::UdpClient:
	case com::CAddress::UdpBindClient:
	case com::CAddress::UdpServer:
	case com::CAddress::Can:
		return true;

	case com::CAddress::TcpConnect:
	case com::CAddress::UdpConnect:
	default:
		return false;
	}
}

bool CIo::setAddress( const com::CAddress& addr ){
	if( addr.getType()!=type() )
		return false;

	close();
	m_address = addr;
	return true;
}

bool CIo::setAddress( const char* addr ){
	com::CAddress a;
	if( a.fromString(addr) )
		return setAddress(a);
	else{
		log().warnning(THISMODULE "地址格式不能解析:%s",addr);
		return false;
	}
}

/**
 * 读取数据
 * @param buf 接收缓冲区
 * @param size 缓冲区大小
 * @return
 * <0 设备异常
 * =0 无数据
 * >0 读取的数据长度
 */
int CIo::read( void* buf,const int& size ){
	if( m_fd<0 )
		return -1;

	int rt = ::read(m_fd,buf,size);
	if( rt>0 ){
		m_rxCnt += rt;
		m_lastRx = dm::CTimeStamp::cur();
	}else if( rt<0 ){
		close();
	}

	return rt;
}

/**
 * 写入数据
 * @param buf 数据缓冲区
 * @param len 缓冲区长度
 * @return
 * <0 设备异常
 * =0 无数据
 * >0 读取的数据长度
 */
int CIo::write( const void* buf,const int& len ){
	if( m_fd<0 )
		return -1;

	int rt;
	if( m_txBySend )
		rt = ::send(m_fd,buf,len,MSG_NOSIGNAL);
	else
		rt = ::write(m_fd,buf,len);

	if( rt>0 ){
		m_txCnt += rt;
		m_lastTx = dm::CTimeStamp::cur();
	}else if( rt<0 ){
		close();
	}

	return rt;
}

bool CIo::open_in( const com::CAddress& /*address*/ ){
	return false;
}

}
}
}


